import {guid} from './util'
import {ClassEvents} from '@/utils/class-events'

// 任务对象封装
export class TaskItem {
  constructor(data = {}) {
    this.guid = guid()
    this.running = false
    this.data = data // 数据对象
    data._tqTask = this // 封装对象的引用
  }
}

let timer

// 默认配置
const defaults = {
  // 并发数
  concurrent: 3,
  // 任务处理 Promise 函数
  taskHandler: (task) => {
    return new Promise(resolve => {
      setTimeout(() => {
        console.log(task)
        resolve(task)
      }, 1000)
    })
  }
}

export class TaskQueue extends ClassEvents {
  constructor(options = {}) {
    super()
    this.tasks = [] // 存储任务对象
    this.executing = [] // Promise 任务数组
    Object.assign(this, defaults, options)
  }

  // 添加任务
  addTask(item) {
    this.tasks.push(new TaskItem(item))
    clearTimeout(timer)
    timer = setTimeout(() => {
      this.execute()
    }, 300)
  }

  execute() {
    if (!this.tasks.length) {
      // console.log('all done')
      this.$emit('allDone')
      return
    }
    // 过滤正在运行尚未结束的任务
    const availableTask = this.tasks.filter(item => !item.running)
    let lastCount = this.concurrent - this.executing.length
    // console.log('lastCount',lastCount)

    if (!lastCount) {
      return
    }

    let i = 0
    // 判断是否有剩余的资源执行剩余任务
    while (lastCount > 0 && i < availableTask.length) {
      const task = availableTask[i]
      // console.log('last task', this.tasks, i, task)
      i++
      lastCount--

      task.running = true
      const p = this.taskHandler(task).then(tsk => {
        // 清理已完成
        this.executing.splice(this.executing.indexOf(p), 1)
        this.removeTask(tsk)
        // console.log('done', tsk)
        this.$emit('done', tsk)
        // 递归执行
        this.execute()
        return tsk
      })
      this.executing.push(p)
    }
    // Promise.all(this.executing).then(r => {
    //   console.log('done')
    //   this.execute()
    // })
  }

  // 移除任务（在此前需要先取消该任务的Promise）
  removeTask(task) {
    const index = this.tasks.findIndex(v => v.guid === task.guid)
    // console.log('taskHandler then', tsk, index)
    if (index > -1) {
      this.tasks.splice(index, 1)
    }
  }
}
